package com.jiarong.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jiarong.domain.User;
import com.jiarong.domain.vo.UserVo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * <p>回写数据（异步操作）</p>
 * <p>@ResponseBody告诉Spring MVC框架不进行视图跳转，直接进行回写数据</p>
 * <p>@RestController相当于@Controller + @ResponseBody两个注解的结合</p>
 * <p>返回json数据不需要在方法前面加@ResponseBody注解了</p>
 * <p>但使用@RestController这个注解就不能返回jsp、html页面，视图解析器无法解析jsp、html页面</p>
 * <p>使用@GetMapping和@PostMapping这两个注解代替@RequestMapping可读性更高</p>
 *
 * @author 加绒
 * @date 2021/10/27 21:26
 */
@RestController
public class WriteBackDataController extends BaseController {
    /**
     * 通过Spring MVC框架注入的HttpServletResponse对象 使用getWriter().print()回写数据
     *
     * @param response HTTP响应
     * @throws IOException IO异常
     */
    @GetMapping("/test6")
    public void test6(HttpServletResponse response) throws IOException {
        // 解决中文乱码
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().print("我于黄豆之中绽放，亦如蚌埠住了的花朵\uD83D\uDE05");
    }

    /**
     * <p>解决中文乱码需在@RequestMapping中设置produces = "application/json;charset=UTF-8"</p>
     * <p>如果配置了处理器适配器（RequestMappingHandlerAdapter），需要删除produces = "application/json;charset=UTF-8"</p>
     * <p>配置了mvc:annotation-driven需要保留</p>
     *
     * @return 回写字符串
     */
    @GetMapping(value = "/test7", produces = {"application/json;charset=UTF-8", "text/html;charset=UTF-8"})
    public String test7() {
        return "\uD83D\uDE05我于黄豆之中绽放，亦如蚌埠住了的花朵\uD83D\uDE05";
    }

    /**
     * 使用第三方JSON工具返回JSON格式的字符串
     *
     * @param user         “模拟”数据
     * @param objectMapper 第三方JSON工具
     * @return 回写字符串
     */
    @GetMapping(value = "/test8", produces = {"application/json;charset=UTF-8", "text/html;charset=UTF-8"})
    public String test8(User user, ObjectMapper objectMapper) {
        System.out.println("法外狂徒张三");
        user.setUsername("张三");
        user.setAge(18);
        user.setBirthday(new Date());
        String json = null;
        try {
            json = objectMapper.writeValueAsString(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return json;
    }

    /**
     * 通过配置处理器适配器可以直接返回对象（JSON格式）
     *
     * @param user “模拟”数据
     * @return 返回对象
     */
    @GetMapping("/test9")
    public User test9(User user) {
        System.out.println("我看刑");
        user.setUsername("罗翔说刑法");
        user.setAge(30);
        user.setBirthday(new Date());
        return user;
    }

    /**
     * Controller中的业务方法的参数名称要与请求参数的name一致，参数值会自动映射匹配
     *
     * @param username 获得引用数据类型参数 String
     * @param age      获得基本数据类型参数 int
     */
    @GetMapping("/test10")
    public void test10(String username, int age) {
        System.out.println(username);
        System.out.println(age);
    }

    /**
     * Controller中的业务方法的POJO参数的属性名与请求参数的name一致，参数值会自动映射匹配
     *
     * @param user 获得POJO类型参数
     */
    @GetMapping("/test11")
    public void test11(User user) {
        System.out.println(user);
    }

    /**
     * Controller中的业务方法数组名称与请求参数的name一致，参数值会自动映射匹配
     *
     * @param arr 获得数组类型参数
     */
    @GetMapping("/test12")
    public void test12(String[] arr) {
        System.out.println(Arrays.asList(arr));
    }

    /**
     * 获得集合参数时，要将集合参数包装到一个POJO中才可以
     *
     * @param users 获得集合类型参数（封装VO）
     */
    @PostMapping("/test13")
    public void test13(UserVo users) {
        System.out.println(users);
    }

    /**
     * <p>当使用ajax提交时，可以指定contentType为JSON形式</p>
     * <p>在方法参数位置使用@RequestBody可以直接接收集合数据而无需使用POJO进行包装</p>
     *
     * @param users 获得集合类型参数（直接获得）
     */
    @PostMapping("/test14")
    public void test14(@RequestBody List<User> users) {
        System.out.println(users);
    }

    /**
     * <p>当请求的参数名称与Controller的业务方法参数名称不一致时，就需要通过@RequestParam注解显示的绑定</p>
     * <p>value：指定请求参数的名称</p>
     * <p>required：是否需要此参数，默认true</p>
     * <p>defaultValue：默认赋值</p>
     *
     * @param username 请求参数
     */
    @GetMapping("/test15")
    public void test15(@RequestParam(value = "name", required = false,
            defaultValue = "啊这") String username) {
        System.out.println(username);
    }

    /**
     * 在Spring MVC中可以使用占位符进行参数绑定，在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取工作
     *
     * @param name 请求参数
     */
    @GetMapping("/test16/{name}")
    public void test16(@PathVariable(value = "name") String name) {
        System.out.println(name);
    }

    /**
     * 测试自定义日期转换器（因为是Set，所以覆盖了默认的）
     *
     * @param date 日期
     */
    @GetMapping("/test17")
    public void test17(Date date) {
        System.out.println(date);
    }

    /**
     * Spring MVC支持使用原始Servlet API对象作为控制器方法的参数进行注入，在形参注入所需对象，框架会传递相应实参
     *
     * @param request  请求
     * @param response 响应
     * @param session  Session
     */
    @GetMapping("/test18")
    public void test18(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
        System.out.println(request);
        System.out.println(response);
        System.out.println(session);
    }

    /**
     * <p>使用@RequestHeader可以获得请求头信息</p>
     * <p>value：请求头的名称</p>
     * <p>required：是否必须携带此请求头</p>
     *
     * @param header 接收请求头信息
     */
    @GetMapping("/test19")
    public void test19(@RequestHeader(value = "User-Agent", required = false) String header) {
        System.out.println(header);
    }

    /**
     * <p>使用@CookieValue可以获得指定Cookie的值</p>
     * <p>value：指定cookie的名称</p>
     * <p>required：是否必须携带此cookie</p>
     *
     * @param jSessionId 接收Cookie的值
     */
    @GetMapping("/test20")
    public void test20(@CookieValue(value = "JSESSIONID") String jSessionId) {
        System.out.println(jSessionId);
    }

    /**
     * 文件上传（多文件用数组接收，for循环操作）
     *
     * @param uploadFile 待接收对象
     * @throws IOException IO异常
     */
    @PostMapping("/test21")
    public void test21(MultipartFile[] uploadFile) throws IOException {
        for (MultipartFile multipartFile : uploadFile) {
            // 获取文件名称
            String originalFilename = multipartFile.getOriginalFilename();
            // 保存文件
            multipartFile.transferTo(new File("D:\\Backups\\" + originalFilename));
        }
    }
}
